public without sharing class PartsInvoiceApplicationController {

	public String msg {get; private set;}
   	public Boolean isErr {get; private set;}
   	public Boolean isSuccess {get;private set ;}

   	public String backId {get;private set;}

   	public String dataJson {get;private set;}
   	public String saveJson {get; set;}
   	private Boolean isNew ;
   	private  Map<String,DataUtil.SObjectBean> stageObjectMap;
    public Boolean isSaler {get; private set;}
    private String company ; 
    private String salescode ; 
    private String province ; 

    private String parentId; 
    public Boolean isExpired {get;private set;}
    private Boolean isNeedParam ;

    private User u ;

   	private PartsInvoiceApplication__c piva  ;
    public PartsInvoiceApplicationController() {
      isNew = false;
   		backId  = System.currentPageReference().getParameters().get('id');
   		piva = new PartsInvoiceApplication__c();
      stageObjectMap = new  Map<String,DataUtil.SObjectBean>();
      isNeedParam = false;

    }


    public void init(){

   		try {
          

          WorkOrder__c wo  = null;
   			  List<PartsLendingApplication__c> papps  = new List<PartsLendingApplication__c>();
          Map<String,String>companyMap = ImportObject.getPicklistValues('WorkOrder__c','InventoryOrganization__c', true);
   		   User curentU = [select Id,Profile.Name,PriceProvince__c,SubCompany__c from User where Id=:UserInfo.getUserId()];

          if(Id.valueOf(backId).getSobjecttype() == PartsInvoiceApplication__c.Sobjecttype ){//编辑

            piva = [select Id,Status__c ,RelatedWorkOrder__c,OwnerId , InventoryOrganization__c ,InvoiceAccount__c,InvoiceAccount__r.ParentId   from PartsInvoiceApplication__c where Id =:backId];
            
            u = [select Id,Profile.Name,PriceProvince__c,SubCompany__c from User where Id=:piva.OwnerId ];
            parentId = piva.InvoiceAccount__r.ParentId;

            company  = companyMap.get(piva.InventoryOrganization__c);
            
            province = [select PriceProvince__c from User where Id=:piva.OwnerId ].PriceProvince__c ; 
            isSaler = piva.Status__c == '审批中' && !curentU.Profile.Name.contains('工程');

            if(piva.Status__c == '已批准'|| piva.Status__c == '审批中(销售已确认)' || (!isSaler&& piva.Status__c == '审批中'))throw new DmlException('发票申请'+piva.Status__c+'不能修改!');
              wo = [select Id, Case__r.Status,ServiceManufacture__c,ServiceManufacture__r.ExpiryDate__c,PartsInvoicingCustomers__c, InventoryOrganization__c   from WorkOrder__c where Id=:piva.RelatedWorkOrder__c ];
             

   		    }else if(Id.valueOf(backId).getSobjecttype() == WorkOrder__c.Sobjecttype ){//新建
   		    	  
              u = curentU;
             province = u.PriceProvince__c;

              wo = [select Case__r.Status,NotificationAssistant__c  ,Id,ServiceManufacture__c,Technician__r.ClientCode__c, ServiceManufacture__r.ExpiryDate__c, PartsInvoicingCustomers__c,PartsInvoicingCustomers__r.ParentId, InventoryOrganization__c   from WorkOrder__c where Id=:backId ];
              if(wo.Technician__r.ClientCode__c != null ) throw new DmlException('经销商工单不能申请发票!');


              //if(wo.NotificationAssistant__c == null && [select count() from WorkOrderProduct__c where WorkOrder__c =:backId] >0 )throw new DmlException('工单未通知助理,不能申请发票!');
             // if(wo.Case__r.Status == '关闭' ) throw new DmlException('个案已关闭不能申请发票!');

            // if(wo.PartsInvoicingCustomers__c == null || wo.InventoryOrganization__c == null  )isNeedParam = true;
              //throw new DmlException('请在工单上维护使用配件的:申请库存组织和开票客户!');
              parentId = wo.PartsInvoicingCustomers__r.ParentId;



             if([select count() from PartsInvoiceApplication__c where RelatedWorkOrder__c =:backId ] > 0 )throw new DmlException('一个工单只允许有一个发票申请!');
            // //匹配信用期 
             company = companyMap.get(wo.InventoryOrganization__c);
             if(company == null ) company = u.SubCompany__c;
            // List<AccountCredit__c> accCredit =  [select Id, NCCreditDeadline__c from AccountCredit__c where Company__c =:companyMap.get(wo.InventoryOrganization__c) limit 1  ];
   		    	piva.InventoryOrganization__c = wo.InventoryOrganization__c;
            piva.RelatedWorkOrder__c = backId;
            piva.InvoiceAccount__c = wo.PartsInvoicingCustomers__c;
            //piva.CreditPeriod__c = accCredit.isEmpty() ? null : accCredit[0].NCCreditDeadline__c;
            piva.Status__c = '草案中';

   		    	isNew = true;
   		    }else{
   		    	throw new DmlException('打开页面异常!');
   		    }

          if(wo.PartsInvoicingCustomers__c == null  )isNeedParam = true;
          if(wo.ServiceManufacture__c == null ) throw new DmlException('工单服务仪器为空,不能添加配件!');

          isExpired = wo.ServiceManufacture__r.ExpiryDate__c == null  ||  wo.ServiceManufacture__r.ExpiryDate__c.daysBetween(System.today())>=0 ;


          if(company == null )throw new DmlException('请联系管理员维护开票公司对照信息!'); 
          salescode = ImportObject.getPicklistValues('PriceList__c', 'SalesCode__c', false).get(company);
   		    Map<String,Object> dataMap = new Map<String,Object>();
        	List<ProductBean> tmp =  getDetails();
        	if(tmp.isEmpty())throw new DmlException('没有需要开票的配件!');
        	dataMap.put('detail',tmp);

                  //字段
             Map<String,Set<String>> fieldsmap = getFields();
             //字段详情
             Map<String, List<DataUtil.FieldBean>> fbMap = DataUtil.getFieldsBean(fieldsmap,stageObjectMap);
            
            //字段赋值
             Map<String,List<DataUtil.FieldBean>> fields = DataUtil.setFieldsValue(fbMap,DataUtil.getBaseInfo(fbMap,stageObjectMap) );
           
           for (DataUtil.FieldBean fb   :  fields.get('PartsInvoiceApplication__c')) {
                Map<String,Object> vMap  = new Map<String,Object>();
                 
                    if(fb.name == 'InvoiceAccount__c' && piva.InvoiceAccount__c != null ){
                        Account acc = [select Id ,Name from Account where Id=:piva.InvoiceAccount__c];
                        vMap.put('Id', acc.Id );
                        vMap.put('Name', acc.Name );
                        fb.value = vMap;
                    }
                    
                    if(fb.name == 'InventoryOrganization__c')fb.value = piva.InventoryOrganization__c ;
                  
                
             }
            dataMap.put('base',fields);
            dataMap.put('baseObject',DataUtil.getBaseObjectMap(stageObjectMap)); 


           

        	dataJson = EncodingUtil.urlEncode(JSON.serialize(dataMap ),'UTF-8');



   		}catch (Exception e) {
   		    isErr = true ;
    		ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()+e.getStackTraceString()));
   		}
   		
   }


   public List<ProductBean> getDetails(){

   		List<ProductBean> tmp = new List<ProductBean>();
      Set<Id> pids = new Set<Id>();
      List<PartsInvoiceDetails__c> details = [select Id ,WorkOrederProduct__c,WorkOrederProduct__r.Quantity__c, Parts__c ,Parts__r.Name, ConfirmationQuantity__c,
        InvoiceAmount__c,RequestedQuantity__c,Parts__r.NCCode__c,Parts__r.Spec__c,Parts__r.Brand__c,Parts__r.SerialNo__c ,InvoiceAmount_Eng__c, InvoiceAmount_Saler__c
       from PartsInvoiceDetails__c where PartsInvoiceApplication__c =:backId] ;

   		for (PartsInvoiceDetails__c pid  :details ) {
   			  //tmp.add(new ProductBean(pid));
          pids.add(pid.Parts__c);
   		}
      System.debug(pids);
      System.debug(parentId);
      System.debug(piva.InvoiceAccount__c );
      System.debug(salescode);

      Map<Id,PriceList__c> priceListMap =  ImportObject.getPriceListMap(pids, parentId == null ? piva.InvoiceAccount__c : parentId ,  salescode,company,parentId != null   );
      Map<Id,Price__c> priceMap = ImportObject.getPriceMap(pids, u.SubCompany__c,province);

      for (PartsInvoiceDetails__c pid  :details ) {
          tmp.add(new ProductBean(pid,priceListMap.get(pid.Parts__c),priceMap.get(pid.Parts__c)));
          
      }

   		if(!tmp.isEmpty())return tmp;

      List<WorkOrderProduct__c> wpList = [select Id,Quantity__c ,Product__r.Name ,Product__c,InvoiceNo__c ,
        Product__r.NCCode__c,Product__r.Spec__c,Product__r.Brand__c,Product__r.SerialNo__c 
       from WorkOrderProduct__c where WorkOrder__c =:backId  and InvoiceNo__c  > 0 ];

   		for (WorkOrderProduct__c wp  : wpList) {
          pids.add(wp.Product__c);
   		}

      Product__c p  = null ; 
      try {
          p  = [select  Id,Name ,NCCode__c,Spec__c,Brand__c,SerialNo__c from Product__c where NCCode__c = '99001009'];
          pids.add(p.Id);
      }
      catch (Exception e) {
      }
      

      Map<Id,Price__c> priceMap1 = ImportObject.getPriceMap(pids, u.SubCompany__c,province);
      Map<Id,PriceList__c> priceListMap1 =  ImportObject.getPriceListMap(pids, parentId == null ? piva.InvoiceAccount__c : parentId ,  salescode,company,parentId != null   );
      for (WorkOrderProduct__c wp  :wpList ) {
          tmp.add(new ProductBean(wp,priceListMap1.get(wp.Product__c),priceMap1.get(wp.Product__c)));
      }
       //工程技术费
       if(p != null )tmp.add(new ProductBean(p, priceListMap1.get(p.Id),priceMap1.get(p.Id )));
   		return tmp;
   }



   	public void save(){

   		msg = '';
   		try {
   		    Map<String,Object>saveMap = (Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(saveJson, 'UTF-8'));

   		     Map<String,Set<String>> fieldsMap = getFields();
	        Map<String,DataUtil.FieldBean> fbeanMap = DataUtil.getFieldsInfo(PartsInvoiceApplication__c.SObjecttype,fieldsMap.get('PartsInvoiceApplication__c'));


	            Map<String,Object> obj = (Map<String,Object>) saveMap.get('base');

	            for (String field :  obj.keySet()) {

	                if(obj.get(field) == null || DataUtil.getStringValue(obj.get(field)) == '') continue;

	                if(fbeanMap.containsKey(field) )piva.put(field, DataUtil.dataHandler(obj.get(field),fbeanMap.get(field).type.toUpperCase() ));

	            }
	        List<Object> saveList = (List<Object>) saveMap.get('datas');
	        List<PartsInvoiceDetails__c> details = new List<PartsInvoiceDetails__c>();

          Set<Id> pids = new Set<Id>();
	        Set<String> exDetailset = new Set<String>();
          Map<String,String> productMap = new Map<String,String>();
	        for (Object o  : saveList) {
	          	Map<String,Object> mo = (Map<String,Object>)o;
	          	PartsInvoiceDetails__c pd = new PartsInvoiceDetails__c();
	          	pd.Id = DataUtil.getStringValue(mo.get('detailId'));
	          	if(pd.Id != null )  exDetailset.add(pd.Id);
	          	pd.Parts__c = DataUtil.getStringValue(mo.get('productId'));
              pids.add(pd.Parts__c);
	          	pd.Name = DataUtil.getStringValue(mo.get('productName'));
	          	if(mo.get('egnum') != null )pd.RequestedQuantity__c = DataUtil.getDecimalValue(mo.get('egnum'));
	          	if(mo.get('salenum') != null )pd.ConfirmationQuantity__c = DataUtil.getDecimalValue(mo.get('salenum'));

              if(mo.get('engineerPrice') != null )pd.InvoiceAmount_Eng__c = DataUtil.getDecimalValue(mo.get('engineerPrice'));
              if(mo.get('salePrice') != null )pd.InvoiceAmount_Saler__c = DataUtil.getDecimalValue(mo.get('salePrice'));

              productMap.put(pd.Parts__c,DataUtil.getStringValue(mo.get('nccode')));

	          	pd.InvoiceAmount__c = DataUtil.getDecimalValue(mo.get('originPrice'));

	          	pd.WorkOrederProduct__c = DataUtil.getStringValue(mo.get('wpId'));
	          	details.add(pd);
	        }  

          Map<Id,Price__c> priceMap = ImportObject.getPriceMap(pids, u.SubCompany__c,province);

          for ( PartsInvoiceDetails__c pd  : details) {

              Price__c pr = priceMap.get(pd.Parts__c);
              if(pr != null && (pr.AreaDealerPrice__c == null || pr.AreaDealerPrice__c == 0) ) {
                    msg = '存货编码为:'+productMap.get(pd.Parts__c) +'的配件没有一级经销商价，请联系助理维护价格体系一级经销商价！';
                    return;
                }
                if(pr == null) {
                    msg += productMap.get(pd.Parts__c)+' ';
                    continue;
                }
                pd.TerminalGuidancePrice__c = pr.HospitalManagerPrice__c;
                pd.MarketQuotation__c = pr.MarketPrice__c;
                pd.FirstDealerPrice__c = pr.AreaDealerPrice__c;
                pd.SecondaryDealerPrice__c = pr.InvoiceDealerPrice__c;
            
          }
          if(msg.length() > 0 ) msg = '存货编码为:'+msg +'的配件无价格体系，请联系助理新增价格体系！';
          if(msg.length() > 0 && !System.Test.isRunningTest()) return;
	         
	        SavePoint sp = Database.setSavepoint();
	        try {
	          if(isNew )piva.Id = null;
	        	upsert piva ;
	        	delete [select Id from PartsInvoiceDetails__c where Id not in: exDetailset and PartsInvoiceApplication__c =:piva.Id  ];
	        	
	        	for (PartsInvoiceDetails__c pd  : details) {

	        		if(pd.Id == null )pd.PartsInvoiceApplication__c = piva.Id;	

	        	}
	        	if(!details.isEmpty() )upsert details;

	        	isSuccess = true;
	        	msg = '保存成功!';
	        	backId = piva.Id;
	        }
	        catch (Exception e) {
   		   	 	msg = '保存失败:'+e.getMessage()+e.getStackTraceString();
   		   	 	Database.rollback(sp);
	        }

   		}
   		catch (Exception e) {
   		  msg = '保存失败:'+e.getMessage()+e.getStackTraceString();  
   		}

   		
   	}

    public Map<String,Set<String>>  getFields(){
        Map<String,Set<String>> fieldsMap  = new  Map<String,Set<String>>();
        
            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='';
            sb.objname = 'PartsInvoiceApplication__c';
            sb.stype = DataUtil.getSObjectType('PartsInvoiceApplication__c');
            if(!isNew)sb.idvalue = backId;
            sb.type = 'base';
            if(!isNew)sb.condition = ' where Id =\''+backId +'\'';
            stageObjectMap.put('PartsInvoiceApplication__c',sb );
            //'InvoiceAccount__c',
            Set<String>  fields = new Set<String>{'SalesSupervisor__c'};
            if(isNeedParam)fields.add('InvoiceAccount__c');
            if(isNeedParam)fields.add('InventoryOrganization__c');
            fieldsMap.put('PartsInvoiceApplication__c', fields);
        
        return fieldsMap;
    }
    public class ProductBean{
    	public String detailId;
    	public String productId;
    	public String productName ;
    	public Decimal egnum;
    	public Decimal salenum;
    	public Decimal num;
    	//public Decimal price ;
    	public String wpId ;
      public String nccode ;
      public String spec;
      public String brand;
      public String serialno;
      public Decimal originPrice;//原开票价
      public Decimal marketPrice;//市场报价
      public Decimal engineerPrice;//工程师申请开票价
      public Decimal salePrice;//销售确认开票价
      public Decimal firstPrice;//一级经销商价
      public Decimal secondPrice ;//二级经销商价




    	public ProductBean(PartsInvoiceDetails__c pid, PriceList__c price ,Price__c pr  ){
    		
        detailId = pid.Id;
    		productId = pid.Parts__c;
    		productName = pid.Parts__r.Name;
    		egnum = pid.RequestedQuantity__c;
    		salenum = pid.ConfirmationQuantity__c;
    		num = pid.WorkOrederProduct__r.Quantity__c;
    		wpId = pid.WorkOrederProduct__c ;
        nccode = pid.Parts__r.NCCode__c;
        brand = pid.Parts__r.Brand__c;
        spec = pid.Parts__r.Spec__c;
        serialno = pid.Parts__r.SerialNo__c;

        if(pr != null ){
            marketPrice = pr.MarketPrice__c;
            firstPrice = pr.AreaDealerPrice__c;
            secondPrice = pr.InvoiceDealerPrice__c; 
        } 

        if(price != null )originPrice = price.Price__c ;

        engineerPrice = pid.InvoiceAmount_Eng__c;
        salePrice = pid.InvoiceAmount_Saler__c;



    	} 

      public ProductBean(Product__c pid , PriceList__c price ,Price__c pr ){
          productId = pid.Id;
          productName = pid.Name;
          num = 1;
          egnum = 1;
          nccode = pid.NCCode__c;
          brand = pid.Brand__c;
          spec = pid.Spec__c;
          serialno = pid.SerialNo__c;
          if(pr != null ) marketPrice = pr.MarketPrice__c;
          if(price != null )originPrice = price.Price__c ;
      }
    	public ProductBean(WorkOrderProduct__c pid , PriceList__c price ,Price__c pr  ){
    		
        productId = pid.Product__c;
    		productName = pid.Product__r.Name;
    		num = pid.Quantity__c;
    		wpId  = pid.Id;
    		egnum = pid.InvoiceNo__c;

        nccode = pid.Product__r.NCCode__c;
        brand = pid.Product__r.Brand__c;
        spec = pid.Product__r.Spec__c;
        serialno = pid.Product__r.SerialNo__c;
        if(pr != null ) {
          marketPrice = pr.MarketPrice__c;
          firstPrice = pr.AreaDealerPrice__c;
          secondPrice = pr.InvoiceDealerPrice__c;
        }
        if(price != null )originPrice = price.Price__c ;
    		
    	} 
    }





}